package com.zhifa.bigfileupload.controller;

import com.zhifa.bigfileupload.pojo.XssPojo;
import com.zhifa.bigfileupload.service.XssTbService;
import com.zhifa.bigfileupload.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static java.util.concurrent.CompletableFuture.runAsync;

@RestController
@Slf4j
public class XssController {
   //  private static final Logger LOGGER = LoggerFactory.getLogger(Controller.class);
   private final ExecutorService executor = Executors.newSingleThreadExecutor();

    @Autowired
    private XssTbService xssTbService;
    @GetMapping(value = "/save")
    public Result save(@RequestParam(value = "title", defaultValue = "test") String title) {
        log.info("save：{}", title);
        xssTbService.save(title);
        return Result.success();
    }
    //文件上传之前判断是否已经上传过 -1就是没有
    @GetMapping("/search")
    public Result search(){
        List<XssPojo> res = xssTbService.search();
        log.info("search：{}", res);
        return Result.success(res);
    }


    @PostConstruct
    public void init() {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            executor.shutdown();
            try {
                executor.awaitTermination(1, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                System.out.println(e.toString());
            }
        }));
    }
    @GetMapping("/time")
    @CrossOrigin
    public SseEmitter streamDateTime() {

        SseEmitter sseEmitter = new SseEmitter(Long.MAX_VALUE);

        sseEmitter.onCompletion(() -> System.out.println("SseEmitter is completed"));

        sseEmitter.onTimeout(() -> System.out.println("SseEmitter is timed out"));

        sseEmitter.onError((ex) ->System.out.println("SseEmitter got error:" +  ex));

        executor.execute(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    sseEmitter.send(LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd-MM-yyyy hh:mm:ss")));
                    sleep(1, sseEmitter);
                } catch (IOException e) {
                    e.printStackTrace();
                    sseEmitter.completeWithError(e);
                }
            }
            sseEmitter.complete();
        });

        System.out.println("Controller exits");
        return sseEmitter;
    }



    @GetMapping("/run")
    @CrossOrigin
    public SseEmitter doTheJob() {

        SseEmitter sseEmitter = new SseEmitter(Long.MAX_VALUE);

        sseEmitter.onCompletion(() -> System.out.println("SseEmitter is completed"));

        sseEmitter.onTimeout(() -> System.out.println("SseEmitter is timed out"));

        sseEmitter.onError((ex) -> System.out.println("SseEmitter got error:" + ex));

        ObservableProgress progress = new ObservableProgress(100);

        runAsync(() -> {
            sleep(1, sseEmitter);
            pushProgress(sseEmitter, progress.increment(10));
        })
                .thenRunAsync(() -> {
                    sleep(1, sseEmitter);
                    pushProgress(sseEmitter, progress.increment(20));
                })
                .thenRunAsync(() -> {
                    sleep(1, sseEmitter);
                    pushProgress(sseEmitter, progress.increment(10));
                })
                .thenRunAsync(() -> {
                    sleep(1, sseEmitter);
                    pushProgress(sseEmitter, progress.increment(20));
                })
                .thenRunAsync(() -> {
                    sleep(1, sseEmitter);
                    pushProgress(sseEmitter, progress.increment(20));
                })
                .thenRunAsync(() -> {
                    sleep(1, sseEmitter);
                    pushProgress(sseEmitter, progress.increment(20));
                })
                .thenRunAsync(sseEmitter::complete)
                .exceptionally(ex -> {
                    sseEmitter.completeWithError(ex);
                    throw (CompletionException) ex;
                });

        System.out.println("Controller exits");
        return sseEmitter;
    }

    private void pushProgress(SseEmitter sseEmitter, ObservableProgress progress) {
        try {
            System.out.println("Pushing progress: {}" + progress.toString());
            sseEmitter.send(SseEmitter.event().name("Progress").data(progress, MediaType.APPLICATION_JSON));
        } catch (IOException e) {
            System.out.println("An error occurred while emitting progress." +  e);
        }
    }

    private void sleep(int seconds, SseEmitter sseEmitter) {
        try {
            Thread.sleep(seconds * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
            sseEmitter.completeWithError(e);
        }
    }
}
